﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Windows.Markup;
using UIT._2D;
using System.ComponentModel;

namespace UIT.Converters
{
    /// <summary>Converts instances of other types to and from instances of the <see cref="T:System.Windows.Size" /> class. </summary>
    public sealed class SizeConverter : TypeConverter
    {
        /// <summary>Determines whether a class can be converted from a given type to an instance of <see cref="T:System.Windows.Size" />. </summary>
        /// <returns>true if the <paramref name="sourceType" /> can be converted to an instance of <see cref="T:System.Windows.Size" />; otherwise, false.</returns>
        /// <param name="context">Provides contextual information about a component.</param>
        /// <param name="sourceType">Identifies the data type to evaluate for conversion.</param>
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
        }
        /// <summary>Determines whether an instance of <see cref="T:System.Windows.Size" /> can be converted to a different type. </summary>
        /// <returns>true if this instance of <see cref="T:System.Windows.Size" /> can be converted to the <paramref name="destinationType" />; otherwise, false.</returns>
        /// <param name="context">Provides contextual information about a component.</param>
        /// <param name="destinationType">Identifies the data type to evaluate for conversion.</param>
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);
        }
        /// <summary>Attempts to convert a specified object to an instance of <see cref="T:System.Windows.Size" />.</summary>
        /// <returns>The instance of <see cref="T:System.Windows.Size" /> that is created from the converted <paramref name="source" />.</returns>
        /// <param name="context">Provides contextual information about a component.</param>
        /// <param name="culture">Culture-specific information that should be respected during conversion.</param>
        /// <param name="value">The source object that is being converted.</param>
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
#if !SILVERLIGHT
            if (value == null)
            {
                throw base.GetConvertFromException(value);
            }
#endif
            string text = value as string;
            if (text != null)
            {
                return Size.Parse(text);
            }
            return base.ConvertFrom(context, culture, value);
        }
        /// <summary>Attempts to convert an instance of <see cref="T:System.Windows.Size" /> to a specified type. </summary>
        /// <returns>The object that is created from the converted instance of <see cref="T:System.Windows.Size" />.</returns>
        /// <param name="context">Provides contextual information about a component.</param>
        /// <param name="culture">Culture-specific information that should be respected during conversion.</param>
        /// <param name="value">The instance of <see cref="T:System.Windows.Size" /> to convert.</param>
        /// <param name="destinationType">The type that this instance of <see cref="T:System.Windows.Size" /> is converted to.</param>
        /// <exception cref="T:System.NotSupportedException">
        ///   <paramref name="value" /> is null or is not an instance of <see cref="T:System.Windows.Size" />, or if the <paramref name="destinationType" /> is not one of the valid destination types.</exception>
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType != null && value is Size)
            {
                Size size = (Size)value;
                if (destinationType == typeof(string))
                {
                    return size.ConvertToString(null, culture);
                }
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }
        /// <summary>Initializes a new instance of the <see cref="T:System.Windows.SizeConverter" /> class. </summary>
        public SizeConverter()
        {
        }
    }

#if !SILVERLIGHT
    /// <summary>Converts instances of <see cref="T:System.String" /> to and from instances of <see cref="T:System.Windows.Size" />.</summary>
    public class SizeValueSerializer : ValueSerializer
    {
        /// <summary>Determines whether the specified <see cref="T:System.String" /> can be converted to an instance of <see cref="T:System.Windows.Size" />.</summary>
        /// <returns>Always returns true.</returns>
        /// <param name="value">String to evaluate for conversion.</param>
        /// <param name="context">Context information that is used for conversion.</param>
        public override bool CanConvertFromString(string value, IValueSerializerContext context)
        {
            return true;
        }
        /// <summary>Determines whether the specified <see cref="T:System.Windows.Size" /> can be converted to a <see cref="T:System.String" />.</summary>
        /// <returns>true if <paramref name="value" /> can be converted into a <see cref="T:System.String" />; otherwise, false.</returns>
        /// <param name="value">The object to evaluate for conversion.</param>
        /// <param name="context">Context information that is used for conversion.</param>
        public override bool CanConvertToString(object value, IValueSerializerContext context)
        {
            return value is Size;
        }
        /// <summary>Converts a <see cref="T:System.String" /> into a <see cref="T:System.Windows.Size" />.</summary>
        /// <returns>A new instance of <see cref="T:System.Windows.Size" /> based on the supplied <paramref name="value" />.</returns>
        /// <param name="value">The string to convert.</param>
        /// <param name="context">Context information that is used for conversion.</param>
        public override object ConvertFromString(string value, IValueSerializerContext context)
        {
            if (value != null)
            {
                return Size.Parse(value);
            }
            return base.ConvertFromString(value, context);
        }
        /// <summary>Converts an instance of <see cref="T:System.Windows.Size" /> to a <see cref="T:System.String" />.</summary>
        /// <returns>A string representation of the specified <see cref="T:System.Windows.Size" />.</returns>
        /// <param name="value">The object to convert into a string.</param>
        /// <param name="context">Context information that is used for conversion.</param>
        public override string ConvertToString(object value, IValueSerializerContext context)
        {
            if (value is Size)
            {
                return ((Size)value).ConvertToString(null, CultureInfo.InvariantCulture);
            }
            return base.ConvertToString(value, context);
        }
        /// <summary>Initializes a new instance of the <see cref="T:System.Windows.Converters.SizeValueSerializer" /> class.</summary>
        public SizeValueSerializer()
        {
        }
    }
#endif
}
